# encoding: utf-8
import time
from com.stock.mainStock.stockList import stock_list, dongfangcaifu
from com.util.assertUtil import assertMinFlaot, assertAmount
from com.util.loggingUtil import Logs
from com.util.redisCon import RedisCon
import traceback

from com.util.pushUtil import pushDingDing
from multiprocessing.dummy import Pool as ThreadPool

Log = Logs()

redisCon = RedisCon().getCon()


def getDates(o):
    dates = tuple(o).__getitem__(1)
    # 将字符串转为时间 例如20211202102518   -》  14:58
    res = str(dates)[8:10] + ':' + str(dates)[10:12]
    return res

def singleData(o):
    values = tuple(o).__getitem__(0)
    datas = values.split(',')
    singleData = {
        # 收盘
        'close_price': datas[0],
        # 开盘
        # 'open_price': datas[1],
        # 最低价
        # 'lowest_price': datas[2],
        # 最高价
        # 'highest_price': datas[3],
        # 成交量
        'trade_amount': datas[4],  # 股数
        # 成交额
        'trade_val': datas[5],
        # 均价
        'avg_price': datas[6],
        # 换手率
        # 'exchange_ratio': datas[7]
    }
    return singleData



def getRedisMinute(code, marketType):
    """
    获取redis中的分时数据
    :param code:  股票代码
    :param marketType: 市场类型
    :return:
    """
    codeStr = code + '.' + str(marketType)
    timestamp = time.strftime("%Y%m%d", time.localtime())
    list: list = redisCon.zrangebyscore('kline:1000:' + codeStr, float(f"{timestamp}092500"),
                                        float(f"{timestamp}150500"), withscores=True)
    returnDict = dict(map(lambda o : (getDates(o) , singleData(o)),list ))
    return returnDict

def compareMinute(dbResult=dict, httpRes=dict, typeName=str, codestr=str):
    """
    比较分时的数据
    :param dbResult: redis中的分时数据
    :param httpRes:  抓取的数据
    :param typeName: 被抓取的平台
    :return:
    """
    i = 0
    dbTotalAmount = float(0)
    httpTotalAmount = float(0)
    dbTotalVal = float(0)
    httpTotalVal = float(0)

    failDict = {}

    for minute in dbResult.keys():
        # 比较
        dbDatas = dbResult.get(minute)
        httpData: dict = httpRes.get(minute)
        if httpData:
            i = i + 1
            # Log.info('['+codestr+']校验日期' + str(minute))
        else:
            continue
        try:
            # 当前价
            close_price = float(dbDatas['close_price'])
            http_close_price = float(httpData.get('close_price'))
            assertMinFlaot(close_price, http_close_price)
            # 均价
            # avg_price = float(dbDatas['avg_price'])
            # http_avg_price = float(httpData['avg_price'])
            # assertUtil.assertMinFlaot(avg_price, http_avg_price)
            # 成交额
            trade_val = float(dbDatas['trade_val'])
            http_trade_val = float(httpData['trade_val'])
            # assertUtil.assertMinAmount(trade_val, http_trade_val, 2)
            # 成交量
            trade_amount = float(dbDatas['trade_amount']) / 100
            http_trade_amount = float(httpData['trade_amount']) / 100
            # assertUtil.assertMinAmount(trade_amount, http_trade_amount, 2)

            dbTotalAmount += trade_amount
            dbTotalVal += trade_val

            httpTotalAmount += http_trade_amount
            httpTotalVal += http_trade_val

        except:
            Log.info('code:[' + codestr + ']' + minute + ':redis数据库' + str(dbDatas))
            Log.info('code:[' + codestr + ']' + minute + ':' + typeName + str(httpData))
            Log.error('code:[' + codestr + ']' + minute + ':' + traceback.format_exc())
            failDict.setdefault(minute, f"当前价redis[{close_price}]!=dc[{http_close_price}]")

    try:
        assertAmount(dbTotalVal, httpTotalVal, 2)
    except:
        Log.error('Total-code:[' + codestr + ']' + minute + ':' + traceback.format_exc())
        failDict.setdefault('totalAmount,totalVal',
                            f"[{dbTotalAmount}]!=[{httpTotalAmount}],[{dbTotalVal}]!=[{httpTotalVal}]")

    if failDict.__len__() == 1:  # 只有一个不为0的错忽略
        for value in failDict.values():
            if not str(value).__contains__('[0'):
                successMap.setdefault(codestr, i)
            else:
                failMap.setdefault(codestr, failDict)
    elif failDict.__len__() > 1:
        failMap.setdefault(codestr, failDict)
    else:
        successMap.setdefault(codestr, i)

    Log.info('code:[' + codestr + ']总数：' + str(i))


def compareWithMinute(codeStr=str):
    datas = str(codeStr).split(".")
    code = str(datas[0])
    marketType = int(datas[1])
    # 对比分时 过滤了5开头的 过滤了159
    if code.startswith('159') or code.startswith('5'):
        return

    try:
        dbResult = getRedisMinute(code, marketType)
        httpRes = dongfangcaifu().getMinute(code, marketType)
        # stockId = futuDict.get(codeStr)
        # httpRes = getFuTuMinute(stockId)
        if dbResult and httpRes:
            compareMinute(dbResult, httpRes, 'dc', codeStr)
        else:
            Log.error(f"****---codeError{code}---***resData contains None")
    except:
        Log.error(f"****---codeError{code}---***{traceback.format_exc()}")
        failMap.setdefault(code, 'netWorkError')


# 结果
successMap = dict()
failMap = dict()


def run():
    # 对比分时 过滤了5开头的 过滤了159
    codeList = stock_list
    # codeList = codeList[0:100]
    pool = ThreadPool(5)
    pool.map(compareWithMinute, codeList)
    pool.close()
    pool.join()

    totalsize = successMap.__len__() + failMap.__len__()
    resultContent = f"对比分时总数:【{totalsize}】,校验成功:【{successMap.__len__()}】,校验失败【{failMap.__len__()}】,具体请看日志"
    Log.info(f"{resultContent}错误数据：{failMap}")
    pushDingDing(resultContent)


if __name__ == '__main__':
    #run()
    print(getRedisMinute('300015','2'))
